﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Xml.Linq;

namespace mVu
{
  class YouTube : Site
  {
    public override Dictionary<string, string> GetCategories()
    {
      var categories = new Dictionary<string, string>();

      try
      {
        categories.Add(String.Empty, String.Empty);

        string result = GetPageSource("http://gdata.youtube.com/schemas/2007/categories.cat");

        if (!String.IsNullOrEmpty(result))
        {
          XNamespace atom = XNamespace.Get("http://www.w3.org/2005/Atom");
          XDocument doc = XDocument.Parse(result);

          foreach (var cat in doc.Descendants(atom + "category"))
          {
            var label = cat.Attribute("label");
            var term = cat.Attribute("term");

            if (label != null && term != null)
            {
              if (!categories.ContainsKey(label.Value))
              {
                categories.Add(label.Value, String.Format("http://gdata.youtube.com/feeds/api/videos?format=1&category={0}", term.Value));
              }
            }
          }
        }
      }
      catch (Exception ex)
      {
        Utilities.HandleError(ex);
      }

      return categories;
    }

    public override Dictionary<string, string> GetSorts()
    {
      var sorts = new Dictionary<string, string>
                    {
                      {String.Empty, String.Empty},
                      {"Relevance", "relevance"},
                      {"Published", "published"},
                      {"View Count", "viewCount"},
                      {"Rating", "rating"}
                    };

      return sorts;
    }

    public override Dictionary<string, string> GetMediaTypes()
    {
      var types = new Dictionary<string, string>
                    {
                      {"Mobile", "3GP"},
                      {"360p", "FLV"},
                      {"Medium", "MP4"},
                      {"480p", "FLV"},
                      {"720p", "MP4"},
                      {"1080p", "MP4"},
                      {"Mobile (Old)", "FLV"},
                      {"Standard (Old)", "FLV"},
                      {"High (Old)", "3GP"}
                    };

      return types;
    }

    public override List<Thumbnail> GetThumbnails(string baseAddress, string sort, string query, int page)
    {
      var list = new List<Thumbnail>();

      try
      {
        if (String.IsNullOrEmpty(baseAddress))
        {
          baseAddress = "http://gdata.youtube.com/feeds/api/videos?format=1";
        }

        string address = String.IsNullOrEmpty(query) ? baseAddress : baseAddress + "&q=" + query;
        address = address + "&max-results=36&start-index=" + (36 * (page - 1) + 1);
        address = String.IsNullOrEmpty(sort) ? address : address + "&orderby=" + sort;
        string result = GetPageSource(address);

        if (!String.IsNullOrEmpty(result))
        {
          XDocument doc = XDocument.Parse(result);
          XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");
          XNamespace media = XNamespace.Get("http://search.yahoo.com/mrss/");
          XNamespace yt = XNamespace.Get("http://gdata.youtube.com/schemas/2007");

          var entryNodes = doc.Descendants(ns + "entry");

          list.AddRange(from entry in entryNodes
                        let ts = new TimeSpan(0, 0, Convert.ToInt32(entry.Element(media + "group").Element(yt + "duration").Attribute("seconds").Value))
                        select new Thumbnail
                                 {
                                   Url = entry.Element(media + "group").Elements(media + "player").Last().Attribute("url").Value, 
                                   VideoID = entry.Element(ns + "id").Value.Substring(entry.Element(ns + "id").Value.LastIndexOf("/") + 1), 
                                   Title = entry.Element(ns + "title").Value, Image = entry.Element(media + "group").Elements(media + "thumbnail").First().Attribute("url").Value, 
                                   Length = String.Format("({0:00}:{1:00})", ts.Minutes, ts.Seconds)
                                 });
        }
      }
      catch (Exception ex)
      {
        Utilities.HandleError(ex);
      }

      return list;
    }

    public override Dictionary<string, string> GetVideoPaths(string url)
    {
      var dictionary = new Dictionary<string, string>();

      try
      {
        string result = GetPageSource(url.Replace("http://www.youtube.com", "http://www.youtube-nocookie.com"));

        if (!String.IsNullOrEmpty(result))
        {
          int start = result.IndexOf("<param name=\\\"flashvars\\\"");

          if (start > 0)
          {
            int end = result.IndexOf(">", start + 1) + 1;

            if (end > 0)
            {
              string flashvars = result.Substring(start, end - start);
              flashvars = flashvars.Replace("\\\"", "\"");
              flashvars = Uri.UnescapeDataString(flashvars);

              string[] tokens = flashvars.Split('|');
              foreach (string token in tokens)
              {
                string[] info = token.Split(',');

                if (info.Count() == 2 && info[0].StartsWith("http://"))
                {
                  dictionary.Add(_formats[Convert.ToInt32(info[1])], ShortenURL(info[0]));
                }
              }
            }
          }
        }
      }
      catch (Exception ex)
      {
        Utilities.HandleError(ex);
      }

      return dictionary;
    }

    private readonly Dictionary<int, string> _formats = new Dictionary<int, string>
                                                          {
                                                            {17, "Mobile"},
                                                            {34, "360p"},
                                                            {18, "Medium"},
                                                            {35, "480p"},
                                                            {22, "720p"},
                                                            {37, "1080p"},
                                                            {5, "Standard (Old)"},
                                                            {6, "High (Old)"},
                                                            {13, "Mobile (Old)"}
                                                          };


  }
}
